7. 列表与容器 Lists & Containers

一些用于列表的操作符:

范围(Ranges) 是另一种不同于列表的序列,其用于表示连续的整数。其形如range(begin = 0, end, step = 1)。这会给出一个所含区间 [begin,end) ,相邻两数相差 step 的序列。

列表推导(List Comprehension) 是 Python 中一个十分强大的功能。其可以使用原有的列表通过十分简洁的写法得到新的列表,其格式为:

[表达式 for 变量 in 列表] 
[out_exp_res for out_exp in input_list]

or

[表达式 for 变量 in 列表 if 条件]
[out_exp_res for out_exp in input_list if condition]

列表由于具有闭包的性质,即可以通过将一个元素放入列表的方法将该列表放入其它列表中以形成层次结构,我们因此使用 盒子与指针表示法(Box-and-Pointer-Notation) 来表示一个列表。即我们使用一个盒子表示列表,每个盒子内部要么是一个值,要么是一个指向其它复合值(例如函数、列表)的指针,如下图所示:
Pasted image 20250302110449.png

切片(Slicing) 是一种能对列表和范围等序列执行的操作,以得到新的列表。其形如

seq[start = 0:end = len(seq):step = 1]

并返回一个新的列表,其包括原列表 seq 中索引在 [begin,end) 区间中,每隔 step1 个元素取出一个元素。

序列的加法同样会返回一个新的序列,其由两个被操作序列的所有元素组成。

list() 函数与 [] 字面量语法同样可以创建新的列表。

浅拷贝

上述所有操作(切片、加法、list()[])均为 浅拷贝。即,生成的新列表只是包含了对原有元素的引用(即指向相同的内存)。浅拷贝具有以下两点特征:

  • 顶层元素独立:直接修改新列表的顶层结构(如增删、替换元素),不会影响原列表。
  • 嵌套元素共享:如果元素本身是可变对象(如列表、字典),修改这些嵌套对象的内容会影响所有引用它们的列表。
下面这段代码会输出什么结果?

>>> lst = [[]] * 5  
>>> lst[1].append(1)  
>>> lst

了解了浅拷贝的特征后,我们可以构建一些奇特的列表:

Pasted image 20250322102453.png

列表有大量内置方法:

需要注意的是 append 方法直接新开一个元素空间并存放指向 obj 的引用。而 extend 方法是将可迭代对象中的所有元素依次添加到序列末尾(可以理解为这之中隐含了一层解包)。

Python 有许多内置函数接受一个序列并返回一个值:

字符串是一种特殊的序列,用于表示文本数据。其与序列略有不同。例如,我们可以使用 in 来判断某个字符串是否为某个字符串的子串。

Python 有内置函数 reprstr,它们都将某个对象或表达式转化为字符串输出,但规则略有不同:

字符串插值(String Interpolation) 是指将一些表达式的值插入字符串中的技术。Python 首选的字符串插值方式为在某个字符串前添加 f 符号。使用 f 符号修饰的字符串中,所有使用大括号括起来的内容都将被视为一个表达式,该表达式会在当前环境中求值,将值通过 str() 处理后插入大括号所在的地方。

字典(Dictionary) 是 Python 中用于存储 键值对 的容器,同时也是存储 的容器。通过 list 将字典转换为列表时,得到的是包含所有键的列表。若要获得包含所有值的列表,需要进行 list(dict.values())。字典要求键必须是 可哈希(Hashable) 的,即该对象的哈希值在其生命周期内从不改变。整数、浮点数、字符串、元组 都是可哈希的,而 列表、字典 是不可哈希的。

字典同样存在字典推导,其形如:

{<键表达式>: <值表达式> for <变量名> in <可迭代对象> if <过滤条件表达式>}